#ifndef __QTCH_UTIL_H__
#define __QTCH_UTIL_H__

#include <sys/types.h>
#include <cxxabi.h>
#include <typeinfo>
#include <string>
#include <list>
#include <map>
#include <boost/lexical_cast.hpp>
#include <vector>

namespace qtch{

pid_t GetThreadId();
uint64_t GetFiberId();
uint64_t GetCurrentMS();

void Backtrace(std::vector<std::string>& bt, int size = 64, int skip = 1);
std::string BacktraceToString(int size = 64,int skip = 2,const std::string prefix = "");


std::string Time2Str(time_t ts, const std::string& format);
time_t Str2Time(const char* str,const char* format = "%Y-%m-%d %H:%M:%S");
std::string Gmtime2Str(time_t ts, const std::string& format);


template<class T>
const char * TypeToName(){
    static const char * s_name = abi::__cxa_demangle(typeid(T).name(),NULL,NULL,NULL);
    return s_name;
}


class FSUtil{
public:
    static bool isFile(const std::string& fileName);
    static bool isDir(const std::string& dirName);
    static bool listAllFiles(std::vector<std::string>& files,const std::string& folderPath,const std::string& subfix,bool recursive = false);
    static bool MkDir(const std::string& folderPath);
    static bool __mkdir(const std::string& folderPath);
    static bool Unlink(const std::string& filename, bool exist);
    static bool isRunningPidFile(const std::string& pidFile);
    static pid_t getRunningPid(const std::string& pidFile);
    static std::string BaseName(const std::string& filename);
};

class StringUtil{
public:
    static std::string trim(const std::string& str,const std::string& delimit = " \t\r\n");
    static std::vector<std::string> split(const std::string& str, char delim, size_t max = ~0);
    static std::vector<std::string> split(const std::string& str, const char* delim, size_t max = ~0);
    static std::string replace(const std::string& src, char find, char replaceWitch);
    static std::string replace(const std::string& src, char find, const std::string& replaceWitch);
    static std::string toLower(const std::string& v);
    static std::string toUpper(const std::string& v);
    static std::vector<std::string> regexSearch(const std::string& src,const std::string& pattern);
    static bool regexMatch(const std::string& src,const std::string& pattern);
    static std::string regexReplace(const std::string& src, const std::string& pattern, const std::string& replaceWitch);

    static std::string Format(const char* fmt,...);
    static std::string Formatv(const char* fmt, va_list ap);

    static std::string hexstring_from_data(const std::string& input);
    static std::string hexstring_from_data(const void* data,size_t len);
    static std::string data_from_hexstring(const std::string& input);
    static std::string data_from_hexstring(const void* data,size_t len);

    static std::string rand_string(size_t len,const std::string& chars="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
    
};

class TypeUtil {
public:
    static int64_t Atoi(const std::string& str);
    static double Atof(const std::string& str);
    static int64_t Atoi(const char* str);
    static double Atof(const char* str);
    static std::string ItoA(int64_t v);
    static std::string ItoA(uint64_t v);
    static std::string Itof(double v);
    static std::string Itof(float v);
};

class CypherUtil{
public:
    static std::string encodeBase64(const std::string& input);
    static std::string decodeBase64(const std::string& input);
    static std::string encodeBase64(const char* input,int input_len);
    static std::string decodeBase64(const char* input,int input_len);
    static std::string encodeAES_cbc(const std::string& input,const std::string key);
    static std::string encodeAES_cbc(const char* input,size_t input_len,const char* key,size_t key_len);
    static std::string decodeAES_cbc(const std::string& input,const std::string key);
    static std::string decodeAES_cbc(const char* input,size_t input_len,const char* key,size_t key_len);
    static std::string encodeUrl(const std::string& input, bool space_as_plus = true);
    static std::string decodeUrl(const std::string& input, bool space_as_plus = true);


};

class HashUtil{
public:
    static std::string md5Sum(const std::string& input);
    static std::string md5Sum(const char* input,size_t input_len);
    static std::string sha256(const std::string& input);
    static std::string sha256(const char* input,size_t input_len);
    static std::string hmacSha256(const std::string& key,const std::string& input);
    static std::string hmacSha256(const char* key,size_t key_len,const char* input,size_t input_len);
    static std::string sha1(const std::string& input);
    static std::string sha1(const char* input,size_t input_len);
    
};


template<class V,class Map,class K>
V GetParamValue(const Map& m,const K& k,const V& def = V()){
    auto it = m.find(k);
    if(it==m.end()){
        return def;
    }
    try{
        return boost::lexical_cast<V>(it->second);
    }catch(...){
    }
    return def;
}

template<class V,class Map,class K>
bool CheckParamValue(const Map& m,const K& k,V& v){
    auto it = m.find();
    if(it==m.end()){
        return false;
    }
    try{
        v = boost::lexical_cast<V>(it->second);
        return true;
    }catch(...){
    }
    return false;
}

}


#endif